home *** CD-ROM | disk | FTP | other *** search
/ MACD 5 / MACD 5.bin / workbench / wb / czesc_3 / reyes / reyes.c < prev    next >
C/C++ Source or Header  |  1997-12-31  |  31KB  |  1,215 lines

  1. /*
  2.  * REyes 
  3.  *
  4.  * A screen blanker for the Retina graphics card.
  5.  * By Michael Heinz, 8 January, 1994
  6.  *
  7.  * Main routines
  8.  *
  9.  * $Log: REyes.c $
  10.  * Revision 1.2  1994/02/07  17:44:57  mheinz
  11.  * Added RCS stuff.
  12.  *
  13.  */
  14.  
  15. #include <exec/memory.h>
  16. #include <exec/ports.h>
  17. #include <exec/execbase.h>
  18. #include <graphics/displayinfo.h>
  19. #include <intuition/intuitionbase.h>
  20. #include <intuition/gadgetclass.h>
  21. #include <libraries/commodities.h>
  22. #include <libraries/gadtools.h>
  23. #include <dos/dosextens.h>
  24. #include <dos/dostags.h>
  25. #include <utility/tagitem.h>
  26.  
  27. #include <clib/alib_protos.h>
  28. #include <clib/commodities_protos.h>
  29. #include <clib/dos_protos.h>
  30. #include <clib/exec_protos.h>
  31. #include <clib/gadtools_protos.h>
  32. #include <clib/graphics_protos.h>
  33. #include <clib/intuition_protos.h>
  34. #include <clib/macros.h>
  35. #include <clib/retina_protos.h>
  36. #include <retina/retina.h>
  37.  
  38. #include <string.h>
  39. #include <stdlib.h>
  40.  
  41. #include <pragmas/commodities_pragmas.h>
  42. #include <pragmas/dos_pragmas.h>
  43. #include <pragmas/exec_pragmas.h>
  44. #include <pragmas/gadtools_pragmas.h>
  45. #include <pragmas/graphics_pragmas.h>
  46. #include <pragmas/intuition_pragmas.h>
  47. #include <pragmas/retina_pragmas.h>
  48.  
  49. #ifdef SMALLEYES
  50. #include "smalleyes.h"
  51. #else
  52. #include "retinaeyes.h"
  53. #endif
  54.  
  55. UBYTE *VersionString = "$VER: REyes 1.3 (By Michael Heinz)";
  56.  
  57. #define NORMAL_WIDE 640
  58. #define NORMAL_HIGH 480
  59. #define SMALL_WIDE 320
  60. #define SMALL_HIGH 240
  61.  
  62. void
  63. chkabort(void)
  64. {
  65. }
  66.  
  67. /*
  68.  * Common Definitions
  69.  */
  70.  
  71. extern struct ExecBase *SysBase;
  72. extern struct DosLibrary *DOSBase;
  73. struct IntuitionBase *IntuitionBase;
  74. struct RetinaBase *RetinaBase;
  75. struct Library *CxBase, *GadToolsBase, *IconBase;
  76.  
  77. #define FINDPROCPORT (&((struct Process *)SysBase->ThisTask)->pr_MsgPort)
  78.  
  79.  
  80. /*
  81.  * A handy request structure for reporting that we've up and died.
  82.  */
  83. struct EasyStruct quitreq =
  84. {
  85.     sizeof(struct EasyStruct),
  86.     0,
  87.     "REyes",
  88.     "REyes has suffered an untimely demise\ndue to: %s",
  89.     "OK|OK"
  90. };
  91.  
  92. void 
  93. Error(char *s)
  94. {
  95.     if (s) EasyRequest(NULL,&quitreq,NULL,s);
  96. }
  97.  
  98. /*
  99.  * Definitions for our Commodity
  100.  */
  101. struct NewBroker NewBroker =
  102. {NB_VERSION, "REyes ", NULL,
  103.  "Somebody's watching you...", NBU_NOTIFY | NBU_UNIQUE, COF_SHOW_HIDE,
  104.  0, NULL, 0};
  105.  
  106. struct MsgPort *CxPort;
  107.  
  108. UBYTE *PopKey;
  109. UBYTE *BlankKey;
  110.  
  111. #define HOTKEY_OPEN_WINDOW 1L
  112. #define HOTKEY_BLANK_SCREEN 2L
  113.  
  114. #define DEF_CX_PRI 0
  115. #define DEF_POPKEY "control alt s"
  116. #define DEF_BLANKKEY "lamiga s"
  117.  
  118. LONG TimeOut, ClientTimeOut;
  119.  
  120. #define MAX_TIMEOUT        3600L
  121. #define MAX_CLIENT_TIMEOUT 60L
  122.  
  123. #define DEF_TIMEOUT        60L
  124. #define DEF_CLIENT_TIMEOUT 5L
  125.  
  126. #define SERVER_PRI 3L
  127. #define CLIENT_PRI -5L
  128.  
  129. /*
  130.  * Definitions for Eye Movement
  131.  */
  132. #define RAND(m) (Random(m)-(m)/2)
  133.  
  134. #define MAX_SPEED     10L
  135. #define MAX_EYES      10L
  136. #define MAX_CHANCE      100L
  137.  
  138. #define DEF_EYES      5L
  139. #define DEF_SPEED     4L
  140. #define DEF_CHANCE      10L
  141.  
  142. #define DEF_MODE MID_DEFAULT_08
  143.  
  144. LONG NumEyes, Speed, Chance;
  145.  
  146. typedef struct {
  147.     int NumEyes;
  148.     Eyes *Eye[MAX_EYES];
  149. } EyeStruct;
  150.  
  151.  
  152. EyeStruct EyeList;
  153.  
  154. /*
  155.  * Definitions for our configuration window
  156.  */
  157.  
  158. struct NewWindow NewBlankerWindow =
  159. {
  160.     80, 16, 0, 0, 0, 1,
  161.     IDCMP_CLOSEWINDOW | IDCMP_REFRESHWINDOW | IDCMP_GADGETDOWN |
  162.     IDCMP_GADGETUP | IDCMP_VANILLAKEY | SLIDERIDCMP | LISTVIEWIDCMP,
  163.     WINDOWCLOSE | WINDOWDRAG | WINDOWDEPTH | SIMPLE_REFRESH,
  164.     NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0,
  165.     WBENCHSCREEN
  166. };
  167.  
  168. struct Window *BlankerWindow;
  169.  
  170. #define GID_HIDE          1
  171. #define GID_BLANK         2
  172. #define GID_QUIT          3
  173. #define GID_TIMEOUT       4
  174. #define GID_CLIENT        5
  175. #define GID_EYES          6
  176. #define GID_SPEED         7
  177. #define GID_CHANCE          8
  178.  
  179. #ifdef SMALLEYES
  180. #define NUM_GADS         7
  181. #else
  182. #define NUM_GADS         8
  183. #endif
  184.  
  185. struct VisualInfo *BlankerVisualInfo;
  186. struct Gadget *BlankerGadgets;
  187. struct TextAttr BlankerAttr =
  188. {"topaz.font", TOPAZ_EIGHTY, FS_NORMAL, FPF_ROMFONT};
  189.  
  190. struct NewGadget NewBlankerGadgets[NUM_GADS] =
  191. {16, 101, 48, 12, "_Hide", &BlankerAttr, GID_HIDE, PLACETEXT_IN, NULL, NULL,
  192.  80, 101, 48, 12, "_Blank", &BlankerAttr, GID_BLANK, PLACETEXT_IN, NULL, NULL,
  193.  144, 101, 48, 12, "_Quit", &BlankerAttr, GID_QUIT, PLACETEXT_IN, NULL, NULL,
  194.  136, 5, 66, 12, "Timeout", &BlankerAttr, GID_TIMEOUT, PLACETEXT_LEFT, NULL, NULL,
  195.  136, 21, 66, 12, "Client Timeout", &BlankerAttr, GID_CLIENT, PLACETEXT_LEFT, NULL, NULL,
  196.  136, 53, 66, 12, "Speed    ", &BlankerAttr, GID_SPEED, PLACETEXT_LEFT, NULL, NULL,
  197.  136, 69, 66, 12, "Eyes     ", &BlankerAttr, GID_EYES, PLACETEXT_LEFT, NULL, NULL,
  198. #ifndef SMALLEYES
  199.  136, 37, 66, 12, "%Anim    ", &BlankerAttr, GID_CHANCE, PLACETEXT_LEFT, NULL, NULL,
  200. #endif
  201. };
  202.  
  203. UBYTE BlankerGadgetKinds[NUM_GADS] =
  204. {
  205.     BUTTON_KIND, BUTTON_KIND, BUTTON_KIND, INTEGER_KIND, INTEGER_KIND, SLIDER_KIND,
  206.     SLIDER_KIND, 
  207. #ifndef SMALLEYES
  208.     SLIDER_KIND
  209. #endif
  210. };
  211.  
  212. struct TagItem ButtonGadgetTags[] =
  213. {GT_Underscore, (ULONG) '_', TAG_DONE, 0L};
  214.  
  215. struct TagItem TimeGadgetTags[] =
  216. {GTIN_Number, 0L, GTIN_MaxChars, 4L, TAG_DONE, 0L};
  217.  
  218. struct TagItem ClientGadgetTags[] =
  219. {GTIN_Number, 0L, GTIN_MaxChars, 2L, TAG_DONE, 0L};
  220.  
  221. struct TagItem ChanceGadgetTags[] =
  222. {GTSL_Level, 0L, GTSL_Min, 1L, GTSL_Max, MAX_CHANCE, GTSL_LevelFormat, 0L,
  223.  GTSL_LevelPlace, PLACETEXT_LEFT, GTSL_MaxLevelLen, 3L, GA_RELVERIFY, TRUE,
  224.  TAG_DONE, 0L};
  225.  
  226. struct TagItem SpeedGadgetTags[] =
  227. {GTSL_Level, 0L, GTSL_Min, 1L, GTSL_Max, MAX_SPEED, GTSL_LevelFormat, 0L,
  228.  GTSL_LevelPlace, PLACETEXT_LEFT, GTSL_MaxLevelLen, 2L, GA_RELVERIFY, TRUE,
  229.  TAG_DONE, 0L};
  230.  
  231. struct TagItem EyesGadgetTags[] =
  232. {GTSL_Level, 0L, GTSL_Min, 1L, GTSL_Max, MAX_EYES, GTSL_LevelFormat, 0L,
  233.  GTSL_LevelPlace, PLACETEXT_LEFT, GTSL_MaxLevelLen, 2L, GA_RELVERIFY, TRUE,
  234.  TAG_DONE, 0L};
  235.  
  236. struct TagItem *BlankerGadgetTagLists[NUM_GADS] =
  237. {
  238.     &ButtonGadgetTags[0],
  239.      &ButtonGadgetTags[0],
  240.      &ButtonGadgetTags[0],
  241.      &TimeGadgetTags[0],
  242.      &ClientGadgetTags[0],
  243.      &SpeedGadgetTags[0],
  244.      &EyesGadgetTags[0],
  245. #ifndef SMALLEYES
  246.      &ChanceGadgetTags[0],
  247. #endif
  248. };
  249.  
  250. /*
  251.  * Definitions for Server/Client Communication
  252.  */
  253.  
  254. BYTE bsp_TimerSig, bsp_InputSig, bsp_ClientSig;
  255. struct Task *ServerProcess;
  256.  
  257. #define MASK(n) (1L<<(n))
  258.  
  259. struct ClientMessage {
  260.     struct Message bcm_Message;
  261.     struct RetinaScreen *bcm_Screen;
  262.     LONG bcm_Status;
  263.     ULONG bcm_SigMask;
  264.     LONG bcm_Eyes, bcm_Speed, bcm_Chance;
  265. };
  266.  
  267. /*
  268.  * The following functions are used to track resources.
  269.  */
  270. struct ToolNode {
  271.     struct ToolNode *Next;
  272.     void *Tool;
  273.     void (*RemProc) (void *, LONG);
  274.     LONG Size;
  275. }
  276.  
  277. *ToolList;
  278.  
  279. void __regargs
  280. RemTool(void *Tool)
  281. {
  282.     struct ToolNode *Ptr, *OPtr;
  283.  
  284.     Ptr = ToolList;
  285.     OPtr = NULL;
  286.     while (Ptr) {
  287.         if (Ptr->Tool==Tool) {
  288.             Ptr->RemProc(Ptr->Tool,Ptr->Size);
  289.             if (OPtr) 
  290.                 OPtr->Next=Ptr->Next;
  291.             else
  292.                 ToolList=Ptr->Next;
  293.             FreeMem(Ptr,sizeof(struct ToolNode));
  294.             return;
  295.         } else {
  296.             OPtr=Ptr;
  297.             Ptr=Ptr->Next;
  298.         }
  299.     }
  300. }
  301.  
  302. void __regargs
  303. Quit(int ReturnCode, char *s)
  304. {
  305.     while (ToolList)
  306.         RemTool(ToolList->Tool);
  307.     if (ReturnCode) Error(s);
  308.     exit(ReturnCode);
  309. }
  310.  
  311. void __regargs
  312. AddTool(void *NewTool, void *ProcPtr, LONG NewSize, char *errmsg)
  313. {
  314.     struct ToolNode *Ptr;
  315.     void (*NewRemProc) (void *, LONG);
  316.  
  317.     NewRemProc = ProcPtr;
  318.     if (NewTool == NULL)
  319.         Quit(10,errmsg);
  320.  
  321.     if ((Ptr = AllocMem(sizeof(struct ToolNode), MEMF_CLEAR)) == NULL) {
  322.         NewRemProc(NewTool, NewSize);
  323.         Quit(20,"Out of Memory.");
  324.     }
  325.     Ptr->Next = ToolList;
  326.     Ptr->Tool = NewTool;
  327.     Ptr->RemProc = NewRemProc;
  328.     Ptr->Size = NewSize;
  329.     ToolList = Ptr;
  330. }
  331.  
  332. /*
  333.  * Some utility functions
  334.  */
  335.  
  336. void __stdargs
  337. DeleteMsgPortSafely(struct MsgPort *AnyPort)
  338. {
  339.     struct Message *AnyMsg;
  340.  
  341.     while (AnyMsg = GetMsg(AnyPort))
  342.         ReplyMsg(AnyMsg);
  343.     DeleteMsgPort(AnyPort);
  344. }
  345.  
  346. int __regargs
  347. ArgIntMax(char **ToolTypes, char *ID, int Default, int Max)
  348. {
  349.     int Val;
  350.  
  351.     Val = ArgInt(ToolTypes, ID, Default);
  352.     if ((Val < 1) || (Val > Max))
  353.         return Default;
  354.     else
  355.         return Val;
  356. }
  357.  
  358. /*
  359.  * The "InputHandler".  It signals the server process
  360.  * when an input or timer event is received.
  361.  */
  362.  
  363. void __interrupt __saveds
  364. BlankerAction(CxMsg * CxMsg, CxObj * CO)
  365. {
  366.     struct InputEvent *IE;
  367.  
  368.     IE = (struct InputEvent *)CxMsgData(CxMsg);
  369.     if (IE->ie_Class == IECLASS_TIMER)
  370.         Signal(ServerProcess, 1L << bsp_TimerSig);
  371.     else
  372.         Signal(ServerProcess, 1L << bsp_InputSig);
  373. }
  374.  
  375. /*
  376.  * Functions for Handling the Configuration Window
  377.  */
  378.  
  379. LONG
  380. GetNum(struct Gadget *Gadget, LONG * Data, LONG Max)
  381. {
  382.     LONG NewData;
  383.  
  384.     NewData = ((struct StringInfo *)Gadget->SpecialInfo)->LongInt;
  385.     if ((NewData < 1L) || (NewData > Max)) {
  386.         GT_SetGadgetAttrs(Gadget, BlankerWindow, NULL, GTIN_Number, (ULONG) * Data, 
  387.                           TAG_DONE);
  388.         return FALSE;
  389.     } else {
  390.         *Data = NewData;
  391.         return TRUE;
  392.     }
  393. }
  394.  
  395. void
  396. CloseBlankerWindow(void)
  397. {
  398.     if (BlankerWindow) {
  399.         /* 
  400.          * We save the current position of the window
  401.          * so it will re-open in the same place, later.
  402.          */
  403.         NewBlankerWindow.LeftEdge = BlankerWindow->LeftEdge;
  404.         NewBlankerWindow.TopEdge = BlankerWindow->TopEdge;
  405.  
  406.         RemTool(BlankerGadgets);
  407.         RemTool(BlankerVisualInfo);
  408.         RemTool(BlankerWindow);
  409.         BlankerWindow = NULL;
  410.     }
  411. }
  412.  
  413. void
  414. OpenBlankerWindow(void)
  415. {
  416.     struct Gadget *Ptr;
  417.     UWORD Index;
  418.     static char Title[80];
  419.  
  420.     if (BlankerWindow == NULL) {
  421.         strcpy(Title, "REyes = <");
  422.         strcat(Title, PopKey);
  423.         strcat(Title, ">");
  424.  
  425.         if (BlankerWindow = OpenWindowTags(&NewBlankerWindow, WA_Title, Title,
  426.                                                WA_AutoAdjust, TRUE, WA_InnerWidth, 
  427.                                             212, WA_InnerHeight, 118, TAG_DONE)) {
  428.                                
  429.             AddTool(BlankerWindow, CloseWindow, NULL,"Could not open the window.");
  430.  
  431.             if ((BlankerVisualInfo = GetVisualInfo(BlankerWindow->WScreen, TAG_DONE)) 
  432.                 == NULL) {
  433.                 RemTool(BlankerWindow);
  434.                 return;
  435.             }
  436.             AddTool(BlankerVisualInfo, FreeVisualInfo, 0L, 
  437.                     "Couldn't get visual data.");
  438.  
  439.             BlankerGadgets = NULL;
  440.             if ((Ptr = CreateContext(&BlankerGadgets)) == NULL) {
  441.                 RemTool(BlankerVisualInfo);
  442.                 RemTool(BlankerWindow);
  443.                 return;
  444.             }
  445.             AddTool(Ptr, FreeGadgets, 0L,"Couldn't allocate the gadgets.");
  446.  
  447.             /* Here we re-load the gadgets with the current settings. */
  448.             TimeGadgetTags[0].ti_Data = (ULONG) TimeOut;
  449.             ClientGadgetTags[0].ti_Data = (ULONG) ClientTimeOut;
  450.             SpeedGadgetTags[0].ti_Data = (ULONG) Speed;
  451.             SpeedGadgetTags[3].ti_Data = (ULONG) "%2ld";
  452. #ifndef SMALLEYES
  453.             ChanceGadgetTags[0].ti_Data = (ULONG) Chance;
  454.             ChanceGadgetTags[3].ti_Data = (ULONG) "%3ld";
  455. #endif
  456.             EyesGadgetTags[0].ti_Data = (ULONG) NumEyes;
  457.             EyesGadgetTags[3].ti_Data = (ULONG) "%2ld";
  458.  
  459.             for (Index = 0L; Index < NUM_GADS; Index++) {
  460.                 NewBlankerGadgets[Index].ng_TopEdge += BlankerWindow->BorderTop;
  461.  
  462.                 NewBlankerGadgets[Index].ng_VisualInfo = BlankerVisualInfo;
  463.                 Ptr = CreateGadgetA((ULONG) BlankerGadgetKinds[Index], Ptr,
  464.                                     &NewBlankerGadgets[Index], 
  465.                                     BlankerGadgetTagLists[Index]);
  466.                 if (Ptr == NULL) {
  467.                     CloseBlankerWindow();
  468.                     return;
  469.                 }
  470.                 NewBlankerGadgets[Index].ng_TopEdge -= BlankerWindow->BorderTop;
  471.             }
  472.  
  473.             AddGList(BlankerWindow, BlankerGadgets, 0L, -1L, NULL);
  474.             RefreshGadgets(BlankerGadgets, BlankerWindow, NULL);
  475.             GT_RefreshWindow(BlankerWindow, NULL);
  476.         }
  477.     }
  478.     ScreenToFront(BlankerWindow->WScreen);
  479.     WindowToFront(BlankerWindow);
  480.     ActivateWindow(BlankerWindow);
  481. }
  482.  
  483. /*
  484.  * Function to handle the Commodity Stuff
  485.  */
  486.  
  487. void __regargs
  488. HandleCxMsg(CxObj * Broker, CxMsg * CxMsg, LONG * TimeUntilBlank,
  489.             LONG * ThisTimeOut)
  490. {
  491.     ULONG MsgType, MsgID;
  492.  
  493.     MsgType = CxMsgType(CxMsg);
  494.     MsgID = CxMsgID(CxMsg);
  495.     ReplyMsg((struct Message *)CxMsg);
  496.  
  497.     switch (MsgType) {
  498.         case CXM_IEVENT:        /* a hotkey was pressed */
  499.             switch (MsgID) {
  500.                 case HOTKEY_OPEN_WINDOW:
  501.                     OpenBlankerWindow();
  502.                     break;
  503.                 case HOTKEY_BLANK_SCREEN:
  504.                     if (*TimeUntilBlank)
  505.                         *TimeUntilBlank = *ThisTimeOut = 2L;
  506.             }
  507.         case CXM_COMMAND:
  508.             switch (MsgID) {
  509.                 case CXCMD_DISABLE:    /* Message from Exchange
  510.                                          * (except CXCMD_UNIQUE) */
  511.                     (void)ActivateCxObj(Broker, FALSE);
  512.                     break;
  513.                 case CXCMD_ENABLE:
  514.                     (void)ActivateCxObj(Broker, TRUE);
  515.                     break;
  516.                 case CXCMD_UNIQUE:
  517.                 case CXCMD_APPEAR:
  518.                     OpenBlankerWindow();
  519.                     break;
  520.                 case CXCMD_DISAPPEAR:
  521.                     CloseBlankerWindow();
  522.                     break;
  523.                 case CXCMD_KILL:
  524.                     Quit(0,"Normal Termination.");
  525.             }
  526.     }
  527. }
  528.  
  529. #ifdef OBSOLETE
  530. /*
  531.  * These functions have been replaced by defines.
  532.  * They're provided here for hysterical raisins.
  533.  */
  534. void
  535. SpritesOff(struct RetinaScreen *rs)
  536. {
  537.     struct TagItem tags[] =
  538.     {RSP_On, 0L, TAG_DONE, 0L};
  539.  
  540.     Retina_SpriteFunction(rs, tags);
  541. }
  542.  
  543. void
  544. SpritesOn(struct RetinaScreen *rs)
  545. {
  546.     struct TagItem tags[] =
  547.     {RSP_On, 1L, TAG_DONE, 0L};
  548.  
  549.     Retina_SpriteFunction(rs, tags);
  550. }
  551. #else
  552. /*
  553.  * We use defines for these functions just to pick up a little speed.
  554.  */
  555.  
  556. #define SpritesOff(rs)                 \
  557. {                                    \
  558.     struct TagItem tags[] =            \
  559.     {RSP_On, 0L, TAG_DONE, 0L};        \
  560.                                     \
  561.     Retina_SpriteFunction(rs, tags);\
  562. }
  563.     
  564. #define SpritesOn(rs)                \
  565. {                                    \
  566.     struct TagItem tags[] =            \
  567.     {RSP_On, 1L, TAG_DONE, 0L};        \
  568.                                     \
  569.     Retina_SpriteFunction(rs, tags);\
  570. }
  571. #endif
  572.  
  573. /*
  574.  * This, annoyingly enough, is neccessary because Retina_CloseScreen is
  575.  * actually a #pragma and not a real function call.  This means you
  576.  * can't pass a pointer to Retina_CloseScreen as a function argument
  577.  * to AddTool.  By adding this wrapper function, we make AddTool work.
  578.  */
  579. void
  580. DestroyScreen(struct RetinaScreen *rs)
  581. {
  582.     Retina_CloseScreen(rs);
  583. }
  584.  
  585. /*
  586.  * Create Screen will first attempt to open a "normal" resolution screen.
  587.  * If that fails, it will try opening a lower resolution screen.
  588.  * If that fails it will return NULL.
  589.  */
  590. struct RetinaScreen *
  591. CreateScreen(void)
  592. {
  593.     struct RetinaScreen *Screen;
  594.  
  595.     if (!(Screen = Retina_OpenScreen(NORMAL_WIDE, NORMAL_HIGH, MID_DEFAULT_08, 
  596.                                      RSFF_DOUBLEBUFFER, NULL))) 
  597.         if (!(Screen = Retina_OpenScreen(SMALL_WIDE, SMALL_HIGH, MID_DEFAULT_08, 
  598.                                          RSFF_DOUBLEBUFFER, NULL))) 
  599.             return NULL;
  600.     
  601.     Retina_LoadPalette(Screen, 0, EYES_COLS, color_table);
  602.     SpritesOff(Screen);
  603.     return Screen;
  604. }
  605.  
  606. /*
  607.  * Functions for Creating/Deleting the Client Process
  608.  */
  609.  
  610. void __stdargs
  611. DeleteBlankerClient(struct MsgPort * ClientPort)
  612. {
  613.     struct ClientMessage ClientMessage;
  614.  
  615.     /* Send the terminating message to the client. 
  616.      * We kick up the client's priority to ensure a 
  617.      * prompt response.
  618.      */
  619.     Forbid();
  620.     ClientMessage.bcm_Message.mn_ReplyPort = FINDPROCPORT;
  621.     PutMsg(ClientPort, (struct Message *)&ClientMessage);
  622.     
  623.     (void)SetTaskPri(ClientPort->mp_SigTask, SERVER_PRI);
  624.     Permit();
  625.     
  626.     /* Get the response. */
  627.     (void)WaitPort(ClientMessage.bcm_Message.mn_ReplyPort);
  628.     (void)GetMsg(ClientMessage.bcm_Message.mn_ReplyPort);
  629. }
  630.  
  631. struct MsgPort *__regargs
  632. CreateBlankerClient(void *ClientRoutine, struct ClientMessage *ClientMessage)
  633. {
  634.     struct Process *ClientProcess;
  635.     struct TagItem ProcTags[3];
  636.  
  637.     ProcTags[0].ti_Tag = NP_Entry;
  638.     ProcTags[0].ti_Data = (ULONG) ClientRoutine;
  639.     ProcTags[1].ti_Tag = NP_Name;
  640.     ProcTags[1].ti_Data = (ULONG) "ClientProcess";
  641.     ProcTags[2].ti_Tag = TAG_DONE;
  642.  
  643.     if (ClientProcess = CreateNewProc(ProcTags)) {
  644.         ClientMessage->bcm_Message.mn_ReplyPort = FINDPROCPORT;
  645.         PutMsg(&ClientProcess->pr_MsgPort, (struct Message *)ClientMessage);
  646.  
  647.         (void)WaitPort(ClientMessage->bcm_Message.mn_ReplyPort);
  648.         (void)GetMsg(ClientMessage->bcm_Message.mn_ReplyPort);
  649.  
  650.         (void)SetTaskPri((struct Task *)ClientProcess, CLIENT_PRI);
  651.  
  652.         if (ClientMessage->bcm_Status)
  653.             return &ClientProcess->pr_MsgPort;
  654.     }
  655.     return NULL;
  656. }
  657.  
  658. /*
  659.  * Functions for Creating/Drawing/Removing the Eyes
  660.  */
  661.  
  662. LONG __inline
  663. Insure1(LONG val)
  664. {
  665.     return ((val == 0) ? 1 : val);    /* return value that is at least 1 */
  666. }
  667.  
  668. /* 
  669.  * This is a fairly high-speed psuedo random number generator,
  670.  * but it's not to random, though.  Occasionally, it will
  671.  * be non-random enough for a while to cause all the Eyes to
  672.  * move in the same direction (or some such.)  I use it
  673.  * because it's fast and because, with all the collision 
  674.  * detection done now, it's less likely the un-randomness
  675.  * will be noticed.
  676.  */
  677. WORD __regargs
  678. Random(WORD Max)
  679. {
  680.     static ULONG Num = 0L;
  681.     ULONG Sec, Mic;
  682.  
  683.     CurrentTime((ULONG *) & Sec, (ULONG *) & Mic);
  684.  
  685.     Num *= Sec;
  686.     Num += Mic;
  687.  
  688.     while (Num > 32767L)
  689.         Num = Num >> 1;
  690.  
  691.     return (WORD)(Num % Max);
  692. }
  693.  
  694. /*
  695.  * Free up the list of eyes.
  696.  */
  697. void __regargs
  698. DeleteEyes(EyeStruct *EyeList)
  699. {
  700.     LONG i;
  701.  
  702.     for (i=0;i<EyeList->NumEyes;i++) 
  703.         if (EyeList->Eye[i]!=NULL) FreeMem(EyeList->Eye[i],sizeof(Eyes));
  704. }
  705.  
  706. /*
  707.  * Create the list of eyes.
  708.  */
  709. EyeStruct *__regargs
  710. CreateEyes(struct RetinaScreen *Screen,
  711.             LONG NumEyes, LONG Speed)
  712. {
  713.     int Index, i, flag, count;
  714.     Eyes *randomeyes[4];
  715.     
  716.     if (!Screen) return NULL;
  717.     
  718.     randomeyes[0]=&BlueEyes;
  719.     randomeyes[1]=&GreenEyes;
  720.     randomeyes[2]=&VioletEyes;
  721.     randomeyes[3]=&BrownEyes;
  722.  
  723.     /*
  724.      * Create the Eyes
  725.      */
  726.     for (Index = 0; Index < NumEyes; Index++) {
  727.         if (!(EyeList.Eye[Index]=AllocMem(sizeof(Eyes),MEMF_PUBLIC|MEMF_CLEAR))) 
  728.             Quit(20,"Out of Memory!!!");
  729.         CopyMem(randomeyes[Random(4)],EyeList.Eye[Index],sizeof(Eyes));
  730. #ifndef SMALLEYES
  731.         EyeList.Eye[Index]->currentframe=Random(EyeList.Eye[Index]->maxframes);
  732. #else
  733.         EyeList.Eye[Index]->currentframe=0;
  734. #endif
  735.            EyeList.Eye[Index]->xspeed=Insure1(RAND(Speed));
  736.            EyeList.Eye[Index]->yspeed=Insure1(RAND(Speed));
  737.         count=0; flag=1;
  738.  
  739.         /* 
  740.          * We try 4 times to fit an eye pair on the screen.  If we can't, then
  741.          * the screen must be too small for the # of eyes and we truncate the list.
  742.          */
  743.         while (flag & count<4) {
  744.             EyeList.Eye[Index]->xpos=Random(Screen->rs_Width-
  745.                                             EyeList.Eye[Index]->width);
  746.             EyeList.Eye[Index]->ypos=Random(Screen->rs_Height-
  747.                                             EyeList.Eye[Index]->height);
  748.             flag=0;
  749.             for (i=0;i<Index; i++) {
  750.                 /* Looking for overlapping rectangles... */
  751.                 if ((EyeList.Eye[i]->xpos>
  752.                      EyeList.Eye[Index]->xpos-EyeList.Eye[i]->width)&&
  753.                     (EyeList.Eye[i]->xpos<
  754.                      EyeList.Eye[Index]->xpos+EyeList.Eye[Index]->width)&&
  755.                     (EyeList.Eye[i]->ypos>
  756.                      EyeList.Eye[Index]->ypos-EyeList.Eye[i]->height)&&
  757.                     (EyeList.Eye[i]->ypos<
  758.                      EyeList.Eye[Index]->ypos+EyeList.Eye[Index]->height)) {
  759.                     flag=1;
  760.                     break;
  761.                 }
  762.             }
  763.         }
  764.         if (flag) {    /* If we failed to add an Eye pair, truncate the list. */
  765.             NumEyes=Index+1;
  766.             break;
  767.         }
  768.     }
  769.  
  770.     EyeList.NumEyes=NumEyes;
  771.     
  772.     return &EyeList;
  773. }
  774.  
  775. /* move the Eyes and redraw them */
  776.  
  777. void __regargs
  778. DrawEyes(EyeStruct *EyeList, struct RetinaScreen *rs, LONG Chance)
  779. {
  780.     int Index,i;
  781.     Eyes **EL;
  782.  
  783.     /* 
  784.      * This assignment provides a (very mild) speed up buy removing
  785.      * one level of indirection from all the work that's going on below.
  786.      */
  787.     EL=EyeList->Eye;
  788.  
  789.     Chance=Insure1(100-Chance);
  790.  
  791.     /* If we don't have a screen, don't draw on it! (duh.) */
  792.     if (!rs) return; 
  793.  
  794.     for (Index=0; Index<EyeList->NumEyes; Index++) {
  795.         /* Move the Eye. */
  796.         EL[Index]->old_xpos=EL[Index]->xpos;
  797.         EL[Index]->old_ypos=EL[Index]->ypos;
  798.         EL[Index]->xpos+=EL[Index]->xspeed;
  799.         EL[Index]->ypos+=EL[Index]->yspeed;
  800.         
  801.         /* Bounce check */
  802.         if (EL[Index]->xpos<0) { 
  803.             EL[Index]->xpos=0; 
  804.             EL[Index]->xspeed=Insure1(RAND(Speed));
  805.         } else if (EL[Index]->xpos>rs->rs_Width-EL[Index]->width-1) {
  806.             EL[Index]->xpos=rs->rs_Width-EL[Index]->width-1;
  807.             EL[Index]->xspeed=Insure1(RAND(Speed));
  808.         }
  809.         if (EL[Index]->ypos<0) { 
  810.             EL[Index]->ypos=0; 
  811.             EL[Index]->yspeed=Insure1(RAND(Speed));
  812.         } else if (EL[Index]->ypos>rs->rs_Height-EL[Index]->height-1) {
  813.             EL[Index]->ypos=rs->rs_Height-EL[Index]->height-1;
  814.             EL[Index]->yspeed=Insure1(RAND(Speed));
  815.         }
  816.  
  817.         /* 
  818.          * Collision check... 
  819.          * If we detect that we hit one other eye pair, we reverse direction.
  820.          * Note - checking stops after the first collision, otherwise
  821.          * multiple-collisions might cause the eye pair to continue in
  822.          * the same direction (i.e., its direction got negated twice)
  823.          */
  824.         for (i=0;i<EyeList->NumEyes; i++) {
  825.             if (i!=Index) {
  826.                 if ((EL[i]->xpos>EL[Index]->xpos-EL[i]->width)&&
  827.                     (EL[i]->xpos<EL[Index]->xpos+EL[Index]->width)&&
  828.                     (EL[i]->ypos>EL[Index]->ypos-EL[i]->height)&&
  829.                     (EL[i]->ypos<EL[Index]->ypos+EL[Index]->height)) {
  830.  
  831.                     EL[Index]->yspeed= (EL[Index]->yspeed>0)?-Insure1(Random(Speed/2)):Insure1(Random(Speed/2));
  832.                     EL[Index]->xspeed= (EL[Index]->xspeed>0)?-Insure1(Random(Speed/2)):Insure1(Random(Speed/2));
  833.                     EL[Index]->xpos=EL[Index]->old_xpos;
  834.                     EL[Index]->ypos=EL[Index]->old_ypos;
  835.                     break;
  836.                 }
  837.             }
  838.         }
  839. #ifndef SMALLEYES
  840.         /* Are we animating this Eye pair? */
  841.         if (EL[Index]->currentframe) {
  842.             if (!EL[Index]->tic) {
  843.                 EL[Index]->tic++;
  844.             } else {
  845.                 EL[Index]->tic=0;
  846.                 EL[Index]->currentframe=(EL[Index]->currentframe+1)%
  847.                                     EL[Index]->maxframes;
  848.             }
  849.         /* No?  Then roll the dice and see if we should start... */
  850.         } else if (!Random(Chance)) { 
  851.             EL[Index]->currentframe=1;
  852.         }
  853. #endif
  854.             
  855.     }
  856.  
  857.     /* Redraw on the background bitmap... */
  858.     for (Index=0; Index<EyeList->NumEyes; Index++) {
  859.         Retina_WriteRect(EL[Index]->animtable[EL[Index]->currentframe],
  860.                          0,0,
  861.                          EL[Index]->width, RECTMODE_256,
  862.                          rs,EL[Index]->xpos, EL[Index]->ypos,
  863.                          EL[Index]->width, EL[Index]->height, NULL);   
  864.         
  865.     }
  866.         
  867.     /* Swap the bitmaps */
  868.     Retina_SwapBitMap(rs);
  869.  
  870.     /* Erase the old images on the new background bitmap. */
  871.     for (Index=0; Index<EyeList->NumEyes; Index++) {
  872.         Retina_RectFill(rs,EL[Index]->old_xpos,
  873.                         EL[Index]->old_ypos,
  874.                         EL[Index]->old_xpos+EL[Index]->width,
  875.                         EL[Index]->old_ypos+EL[Index]->height);
  876.     }
  877. }
  878.  
  879. /*
  880.  * This is the Client Process's Main Loop
  881.  */
  882.  
  883. void __interrupt __saveds
  884. REyesClientProcess(void)
  885. {
  886.     struct ClientMessage *ClientMessage;
  887.     struct MsgPort *ClientPort;
  888.     struct Task *ServerTask;
  889.     ULONG ServerSigMask;
  890.     struct RetinaScreen *EyesScreen;
  891.     LONG NumEyes, Speed, Chance;
  892.     EyeStruct *EyeList;
  893.  
  894.     /* wait for Server's initial Message */
  895.  
  896.     ClientPort = FINDPROCPORT;
  897.     (void)WaitPort(ClientPort);
  898.     ClientMessage = (struct ClientMessage *)GetMsg(ClientPort);
  899.  
  900.     ServerTask = ClientMessage->bcm_Message.mn_ReplyPort->mp_SigTask;
  901.     ServerSigMask = ClientMessage->bcm_SigMask;
  902.  
  903.     NumEyes = ClientMessage->bcm_Eyes;
  904.     Speed = ClientMessage->bcm_Speed;
  905.     Chance = ClientMessage->bcm_Chance;
  906.     EyesScreen = ClientMessage->bcm_Screen;
  907.  
  908.     if (EyesScreen) {
  909.         if ((EyeList = CreateEyes(EyesScreen, NumEyes, Speed))== NULL) {
  910.             ClientMessage->bcm_Status = FALSE;
  911.             Forbid();
  912.             ReplyMsg((struct Message *)ClientMessage);
  913.             return;
  914.         }
  915.     }
  916.             
  917.     ClientMessage->bcm_Status = TRUE;
  918.     ReplyMsg((struct Message *)ClientMessage);
  919.  
  920.     /* Animate the blanker screen until a termination message is received. */
  921.     while ((ClientMessage = (struct ClientMessage *)GetMsg(ClientPort)) == NULL) {
  922.         if (EyesScreen) DrawEyes(EyeList, EyesScreen, Chance);
  923.     
  924.         /* 
  925.          * We signal the server after each loop so it will know that we're alive.
  926.          */
  927.         Signal(ServerTask, ServerSigMask);
  928.     }
  929.  
  930.     /* We are requested to finish, so we do. */
  931.  
  932.     if (EyeList) DeleteEyes(EyeList);
  933.     Forbid();
  934.     ReplyMsg((struct Message *)ClientMessage);
  935. }
  936.  
  937. /*
  938.  * The Main Loop
  939.  */
  940.  
  941. void
  942. main(LONG argc, UBYTE * argv[])
  943. {
  944.     char **ToolTypes;
  945.     CxObj *Broker, *ObjectList, *Filter;
  946.     struct IntuiMessage *IntMsg;
  947.     CxMsg *BlankerCxMsg;
  948.     LONG ThisTimeOut, TimeUntilBlank, TimeUntilBlack;
  949.     struct RetinaScreen *BlankerScreen = NULL;
  950.     struct MsgPort *ClientPort = NULL;
  951.     int BlankFlag=0;
  952.  
  953.     /* open our Libraries */
  954.     AddTool(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",
  955.                                               37L), CloseLibrary, 0L,
  956.             "Couldn't open the intuition.library.");
  957.     AddTool(IconBase = OpenLibrary("icon.library", 37L), CloseLibrary, 0L,
  958.             "Couldn't open the icon library.");
  959.     AddTool(CxBase = OpenLibrary("commodities.library", 37L), CloseLibrary, 0L,
  960.             "Couldn't open the commoidities library.");
  961.     AddTool(GadToolsBase = OpenLibrary("gadtools.library", 37L), CloseLibrary, 0L,
  962.             "Couldn't open the gadtools library.");
  963.     AddTool(RetinaBase = (struct _xy_RetinaBase *)OpenLibrary("retina.library", 7L), 
  964.             CloseLibrary, 0L,"Couldn't open the Retina library.");
  965.  
  966.     /* get our Arguments */
  967.  
  968.     if (ToolTypes = ArgArrayInit(argc, argv))
  969.         AddTool(ToolTypes, ArgArrayDone, 0L,NULL);
  970.  
  971.     /* get some Signals */
  972.  
  973.     ServerProcess = SysBase->ThisTask;
  974.     if ((bsp_TimerSig = AllocSignal(-1L)) == -1)
  975.         Quit(10,"Could not allocate a signal.");
  976.     AddTool((void *)bsp_TimerSig, FreeSignal, 0L,NULL);
  977.     if ((bsp_InputSig = AllocSignal(-1L)) == -1)
  978.         Quit(10,"Could not allocate a signal.");
  979.     AddTool((void *)bsp_InputSig, FreeSignal, 0L,NULL);
  980.     if ((bsp_ClientSig = AllocSignal(-1L)) == -1)
  981.         Quit(10,"Could not allocate a signal.");
  982.     AddTool((void *)bsp_ClientSig, FreeSignal, 0L,NULL);
  983.  
  984.     /* initialize our Broker = install us as a Commodity */
  985.  
  986.     AddTool(CxPort = CreateMsgPort(), DeleteMsgPortSafely, 0L, 
  987.             "Failed to create a port.");
  988.  
  989.     NewBroker.nb_Descr=&VersionString[6];
  990.     NewBroker.nb_Pri = ArgInt(ToolTypes, "CX_PRIORITY", DEF_CX_PRI);
  991.     NewBroker.nb_Port = CxPort;
  992.     AddTool(Broker = CxBroker(&NewBroker, NULL), DeleteCxObjAll, 0L, 
  993.             NULL);
  994.  
  995.     /* get Time Out, Client Time Out and Display mode */
  996.  
  997.     TimeOut = ArgIntMax(ToolTypes, "TIMEOUT", DEF_TIMEOUT, MAX_TIMEOUT);
  998.     ClientTimeOut = ArgIntMax(ToolTypes, "CLIENTTIMEOUT", DEF_CLIENT_TIMEOUT, 
  999.                                 MAX_CLIENT_TIMEOUT);
  1000.  
  1001.     /* get Parameters for Eye Movement */
  1002.  
  1003.     NumEyes = ArgIntMax(ToolTypes, "EYES", DEF_EYES, MAX_EYES);
  1004.     Speed = ArgIntMax(ToolTypes, "SPEED", DEF_SPEED, MAX_SPEED);
  1005.     Chance = ArgIntMax(ToolTypes, "%ANIM", DEF_CHANCE, MAX_CHANCE);
  1006.  
  1007.     /* install our hot keys */
  1008.  
  1009.     PopKey = ArgString(ToolTypes, "CX_POPKEY", DEF_POPKEY);
  1010.     BlankKey = ArgString(ToolTypes, "BLANKKEY", DEF_BLANKKEY);
  1011.  
  1012.     if ((Filter = HotKey(PopKey, CxPort, HOTKEY_OPEN_WINDOW)) == NULL)
  1013.         Quit(10,"The CX_POPKEY tool type is invalid.");
  1014.     else
  1015.         AttachCxObj(Broker, Filter);
  1016.     if (CxObjError(Filter))
  1017.         Quit(10,"Could not link to the commodity list.");
  1018.  
  1019.     if ((Filter = HotKey(BlankKey, CxPort, HOTKEY_BLANK_SCREEN)) == NULL)
  1020.         Quit(10,"The BLANKKEY tool type is invalid.");
  1021.     else
  1022.         AttachCxObj(Broker, Filter);
  1023.     if (CxObjError(Filter))
  1024.         Quit(10,"Could not link to the commodity list.");
  1025.  
  1026.     /* install our "InputHandler" */
  1027.  
  1028.     ObjectList = CxCustom(BlankerAction, 0L);
  1029.     AttachCxObj(Broker, ObjectList);
  1030.     if (CxObjError(ObjectList))
  1031.         Quit(10,"Could not link to the commodity list.");
  1032.  
  1033.     (void)ActivateCxObj(Broker, TRUE);
  1034.     AddTool(Broker, ActivateCxObj, 0L,"The broker broke.");
  1035.  
  1036.     /* open Window on startup if not forbidden */
  1037.  
  1038.     if (stricmp(ArgString(ToolTypes, "CX_POPUP", ""), "NO"))
  1039.         OpenBlankerWindow();
  1040.  
  1041.     /* 
  1042.      * increase our Priority 
  1043.      * Note that when we quit, our priority will be reset to what it
  1044.      * was before.
  1045.      */
  1046.  
  1047.     AddTool(FindTask(NULL), SetTaskPri, (LONG) SetTaskPri(FindTask(NULL), SERVER_PRI),
  1048.             "Findtask failed!");
  1049.  
  1050.     /* start the Loop */
  1051.  
  1052.     TimeUntilBlank = ThisTimeOut = 10L * TimeOut;
  1053.     TimeUntilBlack = 10L * ClientTimeOut;
  1054.  
  1055.     FOREVER
  1056.     {
  1057.         ULONG Mask;
  1058.  
  1059.         if (BlankerWindow)
  1060.             Mask = Wait(MASK(bsp_TimerSig) | MASK(bsp_InputSig) | MASK(bsp_ClientSig) |
  1061.                         MASK(CxPort->mp_SigBit) | 
  1062.                         MASK(BlankerWindow->UserPort->mp_SigBit) |
  1063.                         SIGBREAKF_CTRL_C);
  1064.         else
  1065.             Mask = Wait(MASK(bsp_TimerSig) | MASK(bsp_InputSig) | MASK(bsp_ClientSig) |
  1066.                         MASK(CxPort->mp_SigBit) | SIGBREAKF_CTRL_C);
  1067.  
  1068.         /* process Window Events */
  1069.  
  1070.         while ((BlankerWindow != NULL) && (IntMsg = 
  1071.             GT_GetIMsg(BlankerWindow->UserPort)))
  1072.             switch (IntMsg->Class) {
  1073.                     struct Gadget *Clicked;
  1074.                     UWORD Code;
  1075.  
  1076.                 case IDCMP_CLOSEWINDOW:
  1077.                     GT_ReplyIMsg(IntMsg);
  1078.                     CloseBlankerWindow();
  1079.                     break;
  1080.                 case IDCMP_REFRESHWINDOW:
  1081.                     GT_BeginRefresh(BlankerWindow);
  1082.                     GT_EndRefresh(BlankerWindow, TRUE);
  1083.                     break;
  1084.                 case IDCMP_GADGETUP:
  1085.                     Code = IntMsg->Code;
  1086.                     Clicked = (struct Gadget *)IntMsg->IAddress;
  1087.                     GT_ReplyIMsg(IntMsg);
  1088.                     switch (Clicked->GadgetID) {
  1089.                         case GID_HIDE:
  1090.                             CloseBlankerWindow();
  1091.                             break;
  1092.                         case GID_QUIT:
  1093.                             Quit(0,"Normal Termination.");
  1094.                         case GID_BLANK:
  1095.                             TimeUntilBlank = ThisTimeOut = 2L;
  1096.                             break;
  1097.                         case GID_TIMEOUT:
  1098.                             if (GetNum(Clicked, &TimeOut, MAX_TIMEOUT))
  1099.                                 TimeUntilBlank = ThisTimeOut = 10L * TimeOut;
  1100.                             break;
  1101.                         case GID_CLIENT:
  1102.                             if (GetNum(Clicked, &ClientTimeOut, MAX_CLIENT_TIMEOUT))
  1103.                                 TimeUntilBlack = 10L * ClientTimeOut;
  1104.                             break;
  1105.                         case GID_EYES:
  1106.                             NumEyes = Code;
  1107.                             break;
  1108.                         case GID_SPEED:
  1109.                             Speed = Code;
  1110.                             break;
  1111.                         case GID_CHANCE:
  1112.                             Chance = Code;
  1113.                             break;
  1114.                     }
  1115.                     break;
  1116.                 case IDCMP_VANILLAKEY:
  1117.                     Code = IntMsg->Code;
  1118.                     GT_ReplyIMsg(IntMsg);
  1119.                     switch ((char)Code) {
  1120.                         case 'H':
  1121.                         case 'h':
  1122.                             CloseBlankerWindow();
  1123.                             break;
  1124.                         case 'Q':
  1125.                         case 'q':
  1126.                             Quit(0,"Normal Termination.");
  1127.                         case 'B':
  1128.                         case 'b':
  1129.                             TimeUntilBlank = ThisTimeOut = 2L;
  1130.                     }
  1131.                     break;
  1132.                 default:
  1133.                     GT_ReplyIMsg(IntMsg);
  1134.             }
  1135.  
  1136.         /* process Commodity Messages */
  1137.  
  1138.         while (BlankerCxMsg = (CxMsg *) GetMsg(CxPort))
  1139.             HandleCxMsg(Broker, BlankerCxMsg, &TimeUntilBlank, &ThisTimeOut);
  1140.  
  1141.         /* check for <CTRL>-C */
  1142.  
  1143.         if (Mask & SIGBREAKF_CTRL_C)
  1144.             Quit(0,"Normal Termination.");
  1145.  
  1146.         /* Input detected, unblank if necessary */
  1147.  
  1148.         if (Mask & MASK(bsp_InputSig)) {
  1149.             if (BlankFlag) {
  1150.                 if (ClientPort)
  1151.                     RemTool(ClientPort);
  1152.                 
  1153.                 if (BlankerScreen) {
  1154.                     SpritesOn(BlankerScreen);
  1155.                     RemTool(BlankerScreen);
  1156.                 } else
  1157.                     Retina_DisplayOn();
  1158.                 BlankFlag=0;
  1159.                 ThisTimeOut = 10L * TimeOut;
  1160.             }
  1161.             TimeUntilBlank = ThisTimeOut;
  1162.         }
  1163.  
  1164.         /* client has confirmed that it is still alive */
  1165.         if (Mask & MASK(bsp_ClientSig)) {
  1166.             if (BlankerScreen) Retina_DisplayOn();
  1167.             TimeUntilBlack = 10L * ClientTimeOut;
  1168.             BlankFlag=1;
  1169.         }
  1170.         /* 1/10 sec is over */
  1171.  
  1172.         if (Mask & MASK(bsp_TimerSig))
  1173.             if (TimeUntilBlank) {
  1174.                 TimeUntilBlank--;
  1175.                 if (TimeUntilBlank == 0L) {    /* Time Out reached, blank
  1176.                                              * the screen */
  1177.                     struct ClientMessage ClientMessage;
  1178.  
  1179.                     BlankFlag=1;
  1180.                     BlankerScreen=CreateScreen();
  1181.                     if (BlankerScreen) 
  1182.                         AddTool(BlankerScreen, DestroyScreen, 0L,NULL);
  1183.                     else
  1184.                         /* do this if we're completely out of video memory. */
  1185.                         Retina_DisplayOff();  
  1186.  
  1187.                     ClientMessage.bcm_Screen = BlankerScreen;
  1188.                     ClientMessage.bcm_SigMask = 1L << bsp_ClientSig;
  1189.                     ClientMessage.bcm_Eyes = NumEyes;
  1190.                     ClientMessage.bcm_Speed = Speed;
  1191.                     ClientMessage.bcm_Chance = Chance;
  1192.  
  1193.                     if (ClientPort = CreateBlankerClient(REyesClientProcess, 
  1194.                         &ClientMessage)) {
  1195.                         TimeUntilBlack = 10L * ClientTimeOut;    
  1196.                         /* try to start Client */
  1197.                         AddTool(ClientPort, DeleteBlankerClient, 0L,NULL);
  1198.                     }
  1199.                 }
  1200.             } else {
  1201.                 if ((BlankerScreen)&&(RetinaBase->rb_FirstScreen != BlankerScreen)) {
  1202.                     Retina_ScreenToFront(BlankerScreen);
  1203.                     SpritesOff(BlankerScreen);
  1204.                 }
  1205.                 if (TimeUntilBlack) {
  1206.                     TimeUntilBlack--;
  1207.                     if (TimeUntilBlack == 0L)
  1208.                         Retina_DisplayOff();    /* Client Time Out
  1209.                                                  * reached, turn entire
  1210.                                                  * screen black */
  1211.                 }
  1212.             }
  1213.     }
  1214. }
  1215.